(function () {
  'use strict';
  var libRoot = function () {
      var href = $('<a>').attr('href', '#').prop('href');
      var i = href.indexOf('/html/');
      return i > 0 ? href.substring(0, i) + '/lib/' : '/lib/';
    }();
  var loadBootstrapDepends = makeDependsLoader([libRoot + 'bootstrap-3.3.5/js/bootstrap.js'], [libRoot + 'bootstrap-3.3.5/css/bootstrap.min.css']);
  var loadResizeDepends = makeDependsLoader([libRoot + 'jquery.resize-0.5.3/jquery.resize.js']);
  var loadJquiDepends = makeDependsLoader([libRoot + 'jquery-ui-1.11.4/jquery-ui.min.js']);
  var loadLayoutDepends = makeDependsLoader([libRoot + 'jquery.layout-1.4.0/jquery.layout.js'], [libRoot + 'jquery.layout-1.4.0/jquery.layout-default.css']);
  var loadSpinDepends = makeDependsLoader([libRoot + 'spin.js-2.3.2/spin.min.js']);
  var loadFueluxDepends = makeDependsLoader([libRoot + 'fuelux-3.15.3/js/fuelux.js'], [libRoot + 'fuelux-3.15.3/css/fuelux.css']);
  var loadFileUploadDepends = makeDependsLoader([libRoot + 'jQuery-File-Upload-9.12.5/js/jquery.fileupload.js'], [libRoot + 'jQuery-File-Upload-9.12.5/css/jquery.fileupload.css']);
  var loadValidationDepends = makeDependsLoader([
      libRoot + 'jquery-validation-1.15.0/jquery.validate.js',
      libRoot + 'jquery-validation-1.15.0/localization/message_zh.js'
    ]);
  var loadDatetimePickerDepends = makeDependsLoader([
      libRoot + 'bootstrap-datetimepicker-2.3.8/js/bootstrap-datetimepicker.js',
      libRoot + 'bootstrap-datetimepicker-2.3.8/js/locales/bootstrap-datetimepicker.zh-CN.js'
    ], [libRoot + 'bootstrap-datetimepicker-2.3.8/css/bootstrap-datetimepicker.css']);
  var loadEchartsDepends = makeDependsLoader([
      libRoot + 'echarts-2.2.7/echarts-all.js',
      libRoot + 'echarts-2.2.7/theme/default.js',
      libRoot + 'echarts-2.2.7/theme/blue.js',
      libRoot + 'echarts-2.2.7/theme/dark.js',
      libRoot + 'echarts-2.2.7/theme/infographic.js'
    ]);
  var loadDataTablesDepends = makeDependsLoader([
      libRoot + 'datatables-1.10.11/js/jquery.dataTables.js',
      libRoot + 'datatables-1.10.11/js/dataTables.bootstrap.min.js',
      libRoot + 'datatables-1.10.11/ext/Scroller/js/dataTables.scroller.min.js',
      libRoot + 'datatables-1.10.11/ext/Select/js/dataTables.select.min.js',
      libRoot + 'datatables-1.10.11/ext/Buttons/js/dataTables.buttons.js',
      libRoot + 'datatables-1.10.11/ext/Buttons/js/buttons.bootstrap.js',
      libRoot + 'datatables-1.10.11/ext/Buttons/js/buttons.colVis.js',
      libRoot + 'datatables-1.10.11/ext/Buttons/js/buttons.flash.js',
      libRoot + 'jszip-2.6.0/jszip.js',
      libRoot + 'datatables-1.10.11/ext/Buttons/js/buttons.html5.js',
      libRoot + 'datatables-1.10.11/ext/Buttons/js/buttons.print.js'
    ], [
      libRoot + 'datatables-1.10.11/css/dataTables.bootstrap.min.css',
      libRoot + 'datatables-1.10.11/ext/Select/css/select.bootstrap.min.css',
      libRoot + 'datatables-1.10.11/ext/Buttons/css/buttons.bootstrap.min.css'
    ]);
  var loadUeditorDepends = makeDependsLoader([
      libRoot + 'ueditor-1.4.3.3/ueditor.config.js',
      libRoot + 'ueditor-1.4.3.3/ueditor.all.js'
    ]);
  var loadFullCalendarDepends = makeDependsLoader([
      libRoot + 'fullcalendar-3.0.1/jquery-ui.custom/jquery-ui.custom.js',
      libRoot + 'fullcalendar-3.0.1/jqueryui-touch-punch/jquery.ui.touch-punch.js',
      libRoot + 'fullcalendar-3.0.1/moment/moment.min.js',
      libRoot + 'fullcalendar-3.0.1/fullcalendar/dist/fullcalendar.js',
      libRoot + 'fullcalendar-3.0.1/bootbox.js/bootbox.js'
    ], [
      libRoot + 'fullcalendar-3.0.1/font-awesome/css/font-awesome.css',
      libRoot + 'fullcalendar-3.0.1/jquery-ui.custom/jquery-ui.custom.css',
      libRoot + 'fullcalendar-3.0.1/fullcalendar/dist/fullcalendar.css',
      libRoot + 'fullcalendar-3.0.1/css/ace-fonts.css',
      libRoot + 'fullcalendar-3.0.1/css/ace.css'
    ]);
  var loadWangEditorDepends = makeDependsLoader([
      libRoot + 'wangEditor-2.0/js/wangEditor.min.js'
    ], [libRoot + 'wangEditor-2.0/css/wangEditor.min.css']);
  var uirouter;
  try {
    uirouter = angular.module('ui.router');
  } catch (e) {
  }
  var mod = angular.module('mt.angular', uirouter ? ['ui.router'] : []);
  mod.run([
    '$q',
    function ($q) {
      loadBootstrapDepends($q);
    }
  ]);
  uirouter && mod.config([
    '$compileProvider',
    '$stateProvider',
    '$urlRouterProvider',
    function ($compileProvider, $stateProvider, $urlRouterProvider) {
      $compileProvider.directive('mtState', function ($urlRouter) {
        return {
          restrict: 'A',
          compile: compile
        };
        function compile(element, attrs, transclude) {
          var name = attrs.mtState;
          var url = '/' + (attrs.stateUrl || name);
          var tmpl = element.attr('mt-state-name', attrs.mtState).removeAttr('mt-state').prop('outerHTML');
          $stateProvider.state(name, {
            url: url,
            template: tmpl
          });
          if (element.attr('default-state') !== undefined)
            $urlRouterProvider.otherwise(url);
          $urlRouter.sync();
          element.remove();
        }
      });
    }
  ]);
  var ueditorIdCounter = 0;
  mod.directive('mtUeditor', [
    '$q',
    function ($q) {
      window.UEDITOR_HOME_URL = libRoot + 'ueditor-1.4.3.3/';
      return {
        restrict: 'A',
        require: '?ngModel',
        link: link
      };
      function link(scope, element, attrs, ngModel) {
        loadUeditorDepends($q).then(function () {
          var option = scope.$eval(attrs.mtUeditor);
          var option = $.extend({}, option, {
              UEDITOR_HOME_URL: libRoot + 'ueditor-1.4.3.3/',
              serverUrl: libRoot + '../jsp/ueditor/controller.jsp'
            });
          var ueditorId = 'ueditor' + ++ueditorIdCounter;
          $('<script type="text/plain">').attr('id', ueditorId).appendTo(element);
          var ue = UE.getEditor(ueditorId, option);
          if (!ngModel)
            return;
          ue.addListener('ready', function () {
            ngModel.$render = function () {
              ue.setContent(ngModel.$viewValue || '');
            };
            ue.setContent(ngModel.$viewValue || '');
          });
          ue.addListener('contentChange', function () {
            if (scope.$$phase) {
              ngModel.$setViewValue(ue.getContent());
            } else {
              scope.$apply(function () {
                ngModel.$setViewValue(ue.getContent());
              });
            }
          });
        });
      }
    }
  ]);

  mod.directive('mtSimpleEditor', [
    '$q',
    function ($q) {
      return {
        restrict: 'A',
        require: '?ngModel',
        link: link
      };
      function link(scope, element, attrs, ngModel) {
        loadUeditorDepends($q).then(function () {
          var option = scope.$eval(attrs.mtSimpleEditor);

          // 创建编辑器
          var editor = new wangEditor(attrs.id);

          if (!ngModel)
            return;

          if(option && option !=''){
            editor.config = $.extend({}, editor.config, option);
          }

          editor.create();

          var htmlContent = editor.$txt.html();
              ngModel.$setViewValue(htmlContent || '');

          editor.onchange = function () {
              // 从 onchange 函数中更新数据
              if (scope.$$phase) {
                var htmlContent = editor.$txt.html();
                ngModel.$setViewValue(htmlContent || '');
              } else {
                scope.$apply(function () {
                  var htmlContent = editor.$txt.html();
                  ngModel.$setViewValue(htmlContent || '');
                });
              }
          };

        });
      }
    }
  ]);

  /** input框 日期格式化 **/
  mod.directive('mtDateFormat', [
    '$filter',
    function ($filter) {
      var dateFilter = $filter('date');
      return {
        restrict: 'A',
        require: '?ngModel',
        link: link
      };
      function link(scope, elm, attrs, ctrl) {
        var defaultOption = "yyyy-MM-dd";
        var option = attrs.mtDateFormat || defaultOption;
        function formatter(value) {  
                // return dateFilter(value, 'yyyy-MM-dd'); //format  
                return dateFilter(value, option); //format  
            }
  
            function parser() {  
                // return ctrl.$modelValue;
                return ctrl.$viewValue;
            }  
  
            ctrl.$formatters.push(formatter);  
            ctrl.$parsers.unshift(parser);
      }
    }
  ]);

  mod.directive('mtDatetimePicker', [
    '$q',
    function ($q) {
      return {
        restrict: 'A',
        link: link
      };
      function link(scope, element, attrs) {
        $q.all([
          loadBootstrapDepends($q),
          loadDatetimePickerDepends($q)
        ]).then(function () {
          var option = scope.$eval(attrs.mtDatetimePicker);
          var datetimepickerobj = element.datetimepicker(option);

          // scope.uploader=uploader;
          var events = [
              'show',
              'hide',
              'changeDate',
              'changeYear',
              'changeMonth',
              'outOfRange'
            ];
          for (var i = 0; i < events.length; ++i)
            datetimepickerobj.on( events[i], makeEventHandler(scope, element, attrs, events[i] + '.et'));
          // uploader.on('show', function (e, data) {

          //   for(var i = 0; i < data.files.length; i++){

          //     if( option.maxSize && data.files[i].size > option.maxSize*1024*1024 ){
          //       alert('文件超过限制大小，请压缩后上传！');
          //       scope.url = null;
          //       scope.status = 'fail';
          //       data.abort();

          //       ngModel && ngModel.$setViewValue(scope.url);
          //       scope.$$phase || scope.$applyAsync();

          //       return false;
          //       break;
                
          //     }
          //   }

          // });


        });
      }
    }
  ]);
  mod.directive('mtShowdown', [
    '$http',
    function ($http) {
      var converter = new showdown.Converter();
      return function link(scope, element, attrs) {
        scope.$watch(function (scope) {
          return scope.$eval(attrs.mtShowdown);
        }, function (newVal, oldVal) {
          $http.get(newVal).then(function (response) {
            var html = converter.makeHtml(response.data);
            element.html(html).find('pre code').each(function (i, block) {
              hljs && hljs.highlightBlock(block);
            });
          });
        });
      };
    }
  ]);  mod.directive('mtFileUpload', [
    '$q',
    function ($q) {
      return {
        restrict: 'A',
        link: link,
        scope: true,
        require: '?ngModel'
      };
      function link(scope, element, attrs, ngModel) {
        $q.all([
          loadBootstrapDepends($q),
          loadJquiDepends($q),
          loadFileUploadDepends($q)
        ]).then(function () {
          var option = scope.$eval(attrs.mtFileUpload);
          scope.status = 'initial';
          var uploader = element.fileupload(option);
          scope.uploader=uploader;
          var events = [
              'add',
              'submit',
              'send',
              'done',
              'fail',
              'always',
              'progress',
              'progressall',
              'start',
              'stop',
              'change',
              'paste',
              'drop',
              'dragover',
              'chunksend',
              'chunkdone',
              'chunkfail',
              'chunkalways'
            ];
          for (var i = 0; i < events.length; ++i)
            uploader.on('fileupload' + events[i], makeEventHandler(scope, element, attrs, events[i] + '.upload.file'));
          uploader.on('fileuploadadd', function (e, data) {

            for(var i = 0; i < data.files.length; i++){

              // 选择一个文件的情况下
              if(i==0) {
                scope.url = null;
              }

              if( option.maxSize && data.files[i].size > option.maxSize*1024*1024 ){
                alert('文件超过限制大小，请压缩后上传！');
                scope.url = null;
                scope.status = 'fail';
                data.abort();

                ngModel && ngModel.$setViewValue(scope.url);
                scope.$$phase || scope.$applyAsync();

                return false;
                break;
                
              }

              var extensionPosition = data.files[i].name.lastIndexOf(".");
              var extension = data.files[i].name.substring(extensionPosition);

              // 禁止的上传可执行类型
              if($.inArray( extension.toLowerCase(), ['.php', '.php3', '.php5', '.phtml', '.asp', '.aspx',
                    '.ascx', '.jsp', '.cfm', '.cfc', '.pl','.bat', '.exe', '.dll', '.reg', '.cgi' ] ) >= 0){
                  alert( '此文件类型禁止上传！请上传其他类型文件！' );
                  return false;
              }

              if (option.extensions && -1 == $.inArray( extension.toLowerCase(), option.extensions ) ) {
                  alert( '文件类型错误,请上传' + option.extensions.toString() + '文件！' );
                  return false;
              }


            }

          });
          uploader.on('fileuploadstart', function (e, data) {
              scope.status = 'start';
              scope.url = null;
              ngModel && ngModel.$setViewValue(scope.url);
              scope.$$phase || scope.$applyAsync();

          });
          uploader.on('fileuploadprogress', function (e, data) {
            if (e.isDefaultPrevented()) {
              return false;
            }

          });
          uploader.on('fileuploadfail', function (e, data) {

              scope.status = 'fail';
              scope.data = data;
              scope.$$phase || scope.$applyAsync();
              return false;

          });
          uploader.on('fileuploaddone', function (e, data) {

                scope.status = 'done';
                scope.data = data;
                var uploadedFileName = data.result.length === 1 ? data.result[0] : data.result;
                if(scope.url != null){
                  scope.urlAry = scope.urlAry?scope.urlAry:[];
                  scope.urlAry.push(uploadedFileName);
                }else{
                  scope.urlAry = [];
                  scope.url = data.result.length === 1 ? data.result[0] : data.result;
                  scope.urlAry.push(uploadedFileName);
                }
                
                if(scope.urlAry.length>1){
                  ngModel && ngModel.$setViewValue(scope.urlAry);
                }else{
                  ngModel && ngModel.$setViewValue(scope.url);
                }
                
                scope.$$phase || scope.$applyAsync();
          });
          ngModel && (ngModel.$render = function () {
            scope.url = ngModel.$viewValue || '';
          });
        });
      }
    }
  ]);
  mod.directive('mtValidate', [
    '$q',
    function ($q) {
      return {
        restrict: 'A',
        link: link
      };
      function link(scope, element, attrs) {
        loadValidationDepends($q).then(function () {
          var option = scope.$eval(attrs.mtValidate);
          var validator = element.validate(option);
          scope.$on('reset.validator', function (event, target) {
            if (!target || element.is(target))
              validator.resetForm();
          });
        });
      }
    }
  ]);
  mod.directive('mtLayout', [
    '$http',
    '$compile',
    '$log',
    '$q',
    function ($http, $compile, $log, $q) {
      return {
        restrict: 'A',
        link: link
      };
      function setup(scope, element, attrs) {
        $q.all([
          loadJquiDepends($q),
          loadLayoutDepends($q),
          loadResizeDepends($q)
        ]).then(function () {
          var option = attrs.mtLayout ? scope.$eval(attrs.mtLayout) : {};
          var mtLayout = element.layout(option);
          element.resize(function () {
            if (element.width() > 0 && element.height() > 0) {
              mtLayout.resizeAll();
            }
          });
          element.children('.ui-layout-pane').on('show.bs.dropdown', function () {
            mtLayout.allowOverflow(this);
          }).on('hidden.bs.dropdown', function () {
            mtLayout.resetOverflow(this);
          });
        });
      }
      function link(scope, element, attrs) {
        if (attrs.layoutUrl) {
          $http.get(attrs.layoutUrl).then(function (response) {
            element.html(response.data);
            $compile(element.contents())(scope);
            setup(scope, element, attrs);
          });
        } else {
          setup(scope, element, attrs);
        }
      }
    }
  ]);
  mod.directive('mtUrl', [
    '$http',
    '$compile',
    '$log',
    function ($http, $compile, $log) {
      return {
        restrict: 'A',
        link: link
      };
      function link(scope, element, attrs) {
        var eh = makeEventHandler(scope, element, attrs, 'load.url');
        scope.$watch(function (scope) {
          return attrs.mtUrl;
        }, function (value) {
          $http.get(value).then(function (response) {
            element.html(response.data);
            $compile(element.contents())(scope);
            eh(value);
          });
        });
      }
    }
  ]);
  mod.directive('mtTabPane', [
    '$q',
    function ($q) {
      return {
        restrict: 'A',
        link: link
      };
      function link(scope, element, attrs) {
        var el = '[data-toggle="tab"][href="#' + attrs.id + '"],[data-toggle="tab"][data-target="#' + attrs.id + '"]';
        $('body').on('show.bs.tab', el, makeEventHandler(scope, element, attrs, 'show.bs.tab'));
        $('body').on('shown.bs.tab', el, makeEventHandler(scope, element, attrs, 'shown.bs.tab'));
        $('body').on('hide.bs.tab', el, makeEventHandler(scope, element, attrs, 'hide.bs.tab'));
        $('body').on('hidden.bs.tab', el, makeEventHandler(scope, element, attrs, 'hidden.bs.tab'));
      }
    }
  ]);
  mod.directive('mtTab', [
    '$q',
    function ($q) {
      return {
        restrict: 'A',
        link: link
      };
      function link(scope, element, attrs) {
        loadBootstrapDepends($q).then(function () {
          element.on('show.bs.tab', makeTabEventHandler(scope, element, attrs, 'show.bs.tab'));
          element.on('shown.bs.tab', makeTabEventHandler(scope, element, attrs, 'shown.bs.tab'));
          element.on('hide.bs.tab', makeTabEventHandler(scope, element, attrs, 'hide.bs.tab'));
          element.on('hidden.bs.tab', makeTabEventHandler(scope, element, attrs, 'hidden.bs.tab'));
          scope.$on('show.tab', function (event, target) {
            var s = element.attr('href') || element.attr('data-target');
            if ($(s).is(target)) {
              element.parent('li').removeClass('active');
              element.tab('show');
            }
          });
        });
      }
      function makeTabEventHandler(scope, element, attrs, eventType) {
        return function (event) {
          var targetSelector = element.attr('data-target') || element.attr('href');
          var target = $(targetSelector);
          if (scope.$$phase) {
            scope.$root.$broadcast(eventType, element, target, event);
          } else {
            scope.$apply(function () {
              scope.$root.$broadcast(eventType, element, target, event);
            });
          }
        };
      }
    }
  ]);
  mod.directive('mtModal', [
    '$q',
    function ($q) {
      return {
        restrict: 'A',
        link: link
      };
      function link(scope, element, attrs) {
        loadBootstrapDepends($q).then(function () {
          element.on('show.bs.modal', makeEventHandler(scope, element, attrs, 'show.bs.modal'));
          element.on('shown.bs.modal', makeEventHandler(scope, element, attrs, 'shown.bs.modal'));
          element.on('hide.bs.modal', makeEventHandler(scope, element, attrs, 'hide.bs.modal'));
          element.on('hidden.bs.modal', makeEventHandler(scope, element, attrs, 'hidden.bs.modal'));
          scope.$on('show.modal', function (event, target) {
            if (element.is(target)) {
              element.modal('show');
            }
          });
        });
      }
    }
  ]);
  mod.directive('mtTree', [
    '$http',
    '$compile',
    '$log',
    '$q',
    function ($http, $compile, $log, $q) {
      return {
        restrict: 'A',
        link: link,
        require: '?ngModel'
      };
      function link(scope, element, attrs, ngModel) {
        $q.all([
          loadSpinDepends($q),
          loadFueluxDepends($q)
        ]).then(function () {
          var defaultOption = {
              dataSource: sampleDataSource,
              multiSelect: false,
              folderSelect: true
            };
          var option = scope.$eval(attrs.mtTree) || defaultOption;
          var mtTree = element.tree(option);
          mtTree.on('selected.fu.tree', makeEventHandler(scope, element, attrs, 'selected.fu.tree'));
          mtTree.on('deselected.fu.tree', makeEventHandler(scope, element, attrs, 'deselected.fu.tree'));
          ngModel && mtTree.on('selected.fu.tree', function () {
            ngModel.$setViewValue(mtTree.tree('selectedItems'));
          });
          ngModel && mtTree.on('deselected.fu.tree', function () {
            ngModel.$setViewValue(mtTree.tree('selectedItems'));
          });
          scope.$on('openFolder.tree', function (event, target) {
            if (!target || element.is(target)) {
              var selectedItem = mtTree.find('.tree-branch.tree-selected');
              mtTree.tree('openFolder', selectedItem);
            }
          });
          scope.$on('updateItem.tree', function (event, target, data) {
            if (!target || element.is(target)) {
              var selectedItem = mtTree.find('.tree-branch.tree-selected');
              selectedItem.data(data);
              selectedItem.children('.tree-branch-header,.tree-item-name').find('.tree-label').text(data.name);
            }
          });
          scope.$on('refresh.tree', function (event, target) {
            if (!target || element.is(target)) {
              element.find('.tree-branch, .tree-item').not('.hide').remove();
              mtTree.tree('render');
            }
          });
          scope.$on('refreshFolder.tree', function (event, target) {
            if (!target || element.is(target)) {
              var selectedItem = mtTree.find('.tree-branch.tree-selected');
              mtTree.tree('refreshFolder', selectedItem);
            }
          });
          scope.$on('refreshParentFolder.tree', function (event, target) {
            if (!target || element.is(target)) {
              var selectedItem = mtTree.find('.tree-branch.tree-selected').parent().closest('.tree-branch');
              mtTree.tree('refreshFolder', selectedItem);
            }
          });
        });
      }
      function sampleDataSource(openedParentData, callback) {
        var childNodesArray = [
            {
              'name': '\u76ee\u5f55\u8282\u70b91',
              'type': 'folder'
            },
            {
              'name': '\u5185\u5bb9\u8282\u70b91',
              'type': 'item'
            },
            {
              'name': '\u76ee\u5f55\u8282\u70b92',
              'type': 'folder'
            },
            {
              'name': '\u5185\u5bb9\u8282\u70b92',
              'type': 'item'
            },
            {
              'name': '\u5185\u5bb9\u8282\u70b93',
              'type': 'item'
            }
          ];
        callback({ data: childNodesArray });
      }
    }
  ]);
  var zTreeSampleData = [
      {
        name: '\u7236\u8282\u70b91 - \u5c55\u5f00',
        open: true,
        children: [
          {
            name: '\u7236\u8282\u70b911 - \u6298\u53e0',
            children: [
              { name: '\u53f6\u5b50\u8282\u70b9111' },
              { name: '\u53f6\u5b50\u8282\u70b9112' },
              { name: '\u53f6\u5b50\u8282\u70b9113' },
              { name: '\u53f6\u5b50\u8282\u70b9114' }
            ]
          },
          {
            name: '\u7236\u8282\u70b912 - \u6298\u53e0',
            children: [
              { name: '\u53f6\u5b50\u8282\u70b9121' },
              { name: '\u53f6\u5b50\u8282\u70b9122' },
              { name: '\u53f6\u5b50\u8282\u70b9123' },
              { name: '\u53f6\u5b50\u8282\u70b9124' }
            ]
          },
          {
            name: '\u7236\u8282\u70b913 - \u6ca1\u6709\u5b50\u8282\u70b9',
            isParent: true
          }
        ]
      },
      {
        name: '\u7236\u8282\u70b92 - \u6298\u53e0',
        children: [
          {
            name: '\u7236\u8282\u70b921 - \u5c55\u5f00',
            open: true,
            children: [
              { name: '\u53f6\u5b50\u8282\u70b9211' },
              { name: '\u53f6\u5b50\u8282\u70b9212' },
              { name: '\u53f6\u5b50\u8282\u70b9213' },
              { name: '\u53f6\u5b50\u8282\u70b9214' }
            ]
          },
          {
            name: '\u7236\u8282\u70b922 - \u6298\u53e0',
            children: [
              { name: '\u53f6\u5b50\u8282\u70b9221' },
              { name: '\u53f6\u5b50\u8282\u70b9222' },
              { name: '\u53f6\u5b50\u8282\u70b9223' },
              { name: '\u53f6\u5b50\u8282\u70b9224' }
            ]
          },
          {
            name: '\u7236\u8282\u70b923 - \u6298\u53e0',
            children: [
              { name: '\u53f6\u5b50\u8282\u70b9231' },
              { name: '\u53f6\u5b50\u8282\u70b9232' },
              { name: '\u53f6\u5b50\u8282\u70b9233' },
              { name: '\u53f6\u5b50\u8282\u70b9234' }
            ]
          }
        ]
      },
      {
        name: '\u7236\u8282\u70b93 - \u6ca1\u6709\u5b50\u8282\u70b9',
        isParent: true
      }
    ];
  mod.directive('mtZtree', function () {
    return {
      restrict: 'A',
      link: link,
      require: '?ngModel'
    };
    function link(scope, element, attrs, ngModel) {
      var option = scope.$eval(attrs.mtZtree);
      var data = scope.$eval(attrs.ztreeData);
      if (!option) {
        option = {};
        data || (data = zTreeSampleData);
      }
      option.callback || (option.callback = {});
      if (option.check && option.check.enable) {
        var original = option.callback.onCheck;
        option.callback.onCheck = function (event, treeId, treeNode) {
          var checkedNodes = ztree.getCheckedNodes(true);
          ngModel && ngModel.$setViewValue(checkedNodes);
          original && original.call(this, event, treeId, treeNode);
        };
        var original = option.callback.onNodeCreated;
        option.callback.onNodeCreated = function (event, treeId, treeNode) {
          var checkedNodes = ztree.getCheckedNodes(true);
          ngModel && ngModel.$setViewValue(checkedNodes);
          original && original.call(this, event, treeId, treeNode);
        };
      } else {
        var original = option.callback.onClick;
        option.callback.onClick = function (event, treeId, treeNode, clickFlag) {
          var selectedNodes = ztree.getSelectedNodes();
          ngModel && ngModel.$setViewValue(selectedNodes);
          original && original.call(this, event, treeId, treeNode, clickFlag);
        };
      }
      var ztree = $.fn.zTree.init(element, option, data);
      attrs.ztreeInit && scope.$eval(attrs.ztreeInit, { $event: [ztree] });
    }
  });
  mod.directive('mtTable', [
    '$http',
    '$compile',
    '$log',
    '$q',
    function ($http, $compile, $log, $q) {
      return {
        restrict: 'A',
        link: link,
        require: '?ngModel'
      };
      function link(scope, element, attrs, ngModel) {
        $q.all([
          loadBootstrapDepends($q),
          loadDataTablesDepends($q)
        ]).then(function () {
          var parent = element.parent();
          var option = scope.$eval(attrs.mtTable);
          var mtTable = element.DataTable(option);
          var events = [
              'preInit.dt',
              'preInit.dt',
              'init.dt',
              'draw.dt',
              'order.dt',
              'page.dt',
              'search.dt',
              'processing.dt',
              'preXhr.dt',
              'xhr.dt',
              'length.dt',
              'error.dt',
              'destroy.dt',
              'select',
              'deselect'
            ];
          for (var i = 0; i < events.length; ++i)
            mtTable.on(events[i], makeEventHandler(scope, element, attrs, events[i]));
          ngModel && (ngModel.$render = function () {
          });
          ngModel && mtTable.on('select', function () {
            ngModel.$setViewValue(Array.prototype.slice.call(mtTable.rows('.selected').data(), 0));
          });
          ngModel && mtTable.on('deselect', function () {
            ngModel.$setViewValue(Array.prototype.slice.call(mtTable.rows('.selected').data(), 0));
          });
          ngModel && mtTable.on('draw.dt', function () {
            if (!ngModel.$viewValue)
              return;
            var data = mtTable.data();
            var selected = ngModel.$viewValue;
            var rows = [];
            for (var j = 0; j < selected.length; ++j) {
              for (var i = 0; i < data.length; ++i) {
                if (_ ? _.isEqual(selected[j], data[i]) : JSON.stringify(selected[j]) == JSON.stringify(data[i])) {
                  rows.push(i);
                  break;
                }
              }
            }
            rows.length ? mtTable.rows(rows).select() : ngModel.$setViewValue([]);
          });
          mtTable.on('init.dt', function () {
            parent.resize(function () {
              if (parent.width() > 0 && parent.height() > 0) {
                mtTable.columns.adjust();
                option && option.scroller && mtTable.scroller.measure();
              }
            });
          });
          mtTable.on('column-sizing.dt', function (e, settings) {
            if (option != null && option.scrollY == '100%' && parent.height() > 0) {
              var container = $(mtTable.table().container());
              var extra = container.height() - container.find('.dataTables_scrollBody').height();
              var oldHeight = container.find('.dataTables_scrollBody').height();
              var newHeight = parent.height() - extra;
              if (oldHeight - newHeight > 16 || newHeight - oldHeight > 16) {
                container.find('.dataTables_scrollBody').height(newHeight);
                option && option.scroller && mtTable.scroller.measure();
              }
            }
          });
          scope.$on('resize.table', function (event, target, paging) {
            if (!target || element.is(target)) {
              mtTable.columns.adjust();
              option && option.scroller && mtTable.scroller.measure();
            }
          });
          scope.$on('refresh.table', function (event, target, paging) {
            if (!target || element.is(target))
              mtTable.draw();
          });
        });
      }
    }
  ]);
  mod.directive('mtFullCalendar', [
    '$http',
    '$compile',
    '$log',
    '$q',
    function ($http, $compile, $log, $q) {
      return {
        restrict: 'A',
        link: link,
        require: '?ngModel'
      };
      function link(scope, element, attrs, ngModel) {
        $q.all([
          loadBootstrapDepends($q),
          loadFullCalendarDepends($q)
        ]).then(function () {
          var parent = element.parent();
          var option = scope.$eval(attrs.mtFullCalendar);
          var mtTable = element.DataTable(option);
        });
      }
    }
  ]);
  mod.directive('mtDynamicTable', [
    '$http',
    '$compile',
    '$log',
    '$q',
    function ($http, $compile, $log, $q) {
      return {
        restrict: 'A',
        link: link,
        require: '?ngModel'
      };
      function link(scope, element, attrs, ngModel) {
        var parent = element.parent();
        var option = scope.$eval(attrs.mtDynamicTable);

        // 修改动态显示thead tableth20170525
        var tableHeadDom = element.find('thead');
        var thdom = "";
        if (tableHeadDom != undefined && tableHeadDom.length > 0) {

          // 本区域内无变量赋值时，取rootscope的值
          if(option.tableHeader != undefined){
            tableHeadDom.append(option.tableHeader);
          }else{
            tableHeadDom.append(scope.$root.tableThead);
          }
          
          // for (var i = 0; i < scope.columnArrObj.length; i++) {
          //     thdom += "<th>" + scope.columnArrObj[i] + "</th>";
          // }
          // tableHeadDom.html(thdom);
        }

        var mtTable = element.DataTable(option);
        var events = [
          'preInit.dt',
          'init.dt',
          'draw.dt',
          'order.dt',
          'page.dt',
          'search.dt',
          'processing.dt',
          'preXhr.dt',
          'xhr.dt',
          'length.dt',
          'error.dt',
          'destroy.dt',
          'select',
          'deselect'
        ];
        for (var i = 0; i < events.length; ++i)
          mtTable.on(events[i], makeEventHandler(scope, element, attrs, events[i]));
        ngModel && (ngModel.$render = function () {
        });
        ngModel && mtTable.on('select', function () {
          ngModel.$setViewValue(Array.prototype.slice.call(mtTable.rows('.selected').data(), 0));
        });
        ngModel && mtTable.on('deselect', function () {
          ngModel.$setViewValue(Array.prototype.slice.call(mtTable.rows('.selected').data(), 0));
        });
        ngModel && mtTable.on('draw.dt', function () {
          if (!ngModel.$viewValue)
            return;
          var data = mtTable.data();
          var selected = ngModel.$viewValue;
          var rows = [];
          for (var j = 0; j < selected.length; ++j) {
            for (var i = 0; i < data.length; ++i) {
              if (_ ? _.isEqual(selected[j], data[i]) : JSON.stringify(selected[j]) == JSON.stringify(data[i])) {
                rows.push(i);
                break;
              }
            }
          }
          rows.length ? mtTable.rows(rows).select() : ngModel.$setViewValue([]);
        });
        mtTable.on('init.dt', function () {

          parent.resize(function () {
            if (parent.width() > 0 && parent.height() > 0) {
              mtTable.columns.adjust();
              option && option.scroller && mtTable.scroller.measure();
            }
          });
        });
        mtTable.on('column-sizing.dt', function (e, settings) {
          if (option != null && option.scrollY == '100%' && parent.height() > 0) {
            var container = $(mtTable.table().container());
            var extra = container.height() - container.find('.dataTables_scrollBody').height();
            var oldHeight = container.find('.dataTables_scrollBody').height();
            var newHeight = parent.height() - extra;
            if (oldHeight - newHeight > 16 || newHeight - oldHeight > 16) {
              container.find('.dataTables_scrollBody').height(newHeight);
              option && option.scroller && mtTable.scroller.measure();
            }
          }
        });
        scope.$on('resize.table', function (event, target, paging) {
          if (!target || element.is(target)) {
            mtTable.columns.adjust();
            option && option.scroller && mtTable.scroller.measure();
          }
        });
        scope.$on('refresh.table', function (event, target, paging) {
          if (!target || element.is(target))
            mtTable.draw();
        });

        //// click 增加事件处理 无效
        //element.find('td').bind('click', function(){
        //
        //    /*handle click*/
        //    scope.$apply(function() {
        //        var content = $compile(scope);
        //        element.append(content);
        //    })
        //});
      }
    }
  ]);
  mod.directive('mtEcharts', [
    '$rootScope',
    '$log',
    '$q',
    function ($rootScope, $log, $q) {
      return {
        restrict: 'A',
        link: link
      };
      function setup(scope, element, attrs, theme, option) {
        var mtChart = echarts.init(element[0], theme || 'default');
        option && mtChart.setOption(option);
        angular.forEach(echarts.config.EVENT, function (value, key) {
          mtChart.on(value, makeEventHandler(scope, element, attrs, value + '.echarts'));
        });
        return mtChart;
      }
      function link(scope, element, attrs) {
        $q.all([
          loadEchartsDepends($q),
          loadResizeDepends($q)
        ]).then(function () {
          var mtChart, option, theme, ratio, tmpl, data;
          theme = scope.$eval(attrs.echartsTheme);
          ratio = +scope.$eval(attrs.echartsRatio);
          tmpl = scope.$eval(attrs.echartsSeries);
          element.resize(initialResizeHandler);
          function initialResizeHandler() {
            if (element.width() > 0 && ratio > 0) {
              var nh = Math.round(element.width() / ratio);
              nh != element.height() && element.height(nh);
            }
            if (element.width() > 0 && element.height() > 0) {
              element.removeResize(initialResizeHandler);
              mtChart = setup(scope, element, attrs, theme, option);
              element.resize(finalResizeHandler);
            }
          }
          function finalResizeHandler() {
            if (element.width() > 0 && ratio > 0) {
              var nh = Math.round(element.width() / ratio);
              nh != element.height() && element.height(nh);
            }
            mtChart.resize();
          }
          scope.$watch(function () {
            option = scope.$eval(attrs.mtEcharts);
            return option;
          }, function (newVal, oldVal) {
            if (!option || !option.series || !(option.series instanceof Array)) {
              $log.warn('mt-charts:', 'invalid option -', option);
              return;
            }
            mtChart && mtChart.setOption(option, true);
          });
          scope.$watch(function () {
            data = scope.$eval(attrs.echartsData);
            return data;
          }, function (newVal, oldVal) {
            var data = newVal;
            if (!option || !data)
              return;
            if (!(data.cols instanceof Array) || !(data.rows instanceof Array) || !(data.data instanceof Array)) {
              $log.warn('mt-echarts:', 'invalid data -', data);
              return;
            }
            for (var i = 0; i < data.data.length && i < data.rows.length; ++i) {
              if (i >= option.series.length) {
                option.series[i] = $.extend(true, {}, tmpl || option.series[option.series.length - 1]);
              }
              switch (option.series[i].type) {
              case 'line':
              case 'bar':
                processEchartsLineBarOption(option, i, data);
                break;
              case 'pie':
              case 'map':
              case 'gauge':
                processEchartsPieMapGaugeOption(option, i, data);
                break;
              case 'radar':
                processEchartsRadarOption(option, i, data);
                break;
              }
            }
            if (i < option.series.length)
              option.series.splice(i, option.series.length - i);
            mtChart && mtChart.setOption(option, true);
          });
        });
      }
    }
  ]);

  /**
   * 新闻滚动指令
   */
  mod.directive('mtNewsTicker', function ($interval, $timeout) {
    return {

      restrict: 'A',
      scope: true,
      compile: function () {

        return function (scope, element, attributes) {

          var timing,
              timingEffect,
              timingEffectDivideBy = 4,
              isHovered = false,
              innerTime = false,
              start = false;

          if (attributes.timing) {
            timing = attributes.timing;
            timingEffect = timing / timingEffectDivideBy;
          } else {
            timing = 5000;
            timingEffect = timing / timingEffectDivideBy / timingEffectDivideBy * 2;
          }

          scope.$watch(element, function () {

            var list = element,
                items = element.find('li'),
                itemFirst;


            if (items.length) {
              list.addClass('active');

              start = $interval(function () {

                /*cancel the callback function for fade-out and makes the ticker steady.*/
                if (isHovered) {
                  $timeout.cancel(innerTime);
                  return;
                }

                items = list.children('li');
                itemFirst = angular.element(items[0]);

                itemFirst.addClass('fade-out minus-margin-top');

                $timeout(function () {
                  itemFirst.removeClass('minus-margin-top');
                  list.append(itemFirst);

                  innerTime = $timeout(function () {
                    items.removeClass('fade-out');
                  }, timingEffect);

                }, timingEffect);

              }, timing);

            } else {
              console.warn('no items assigned to ticker! Ensure you have correctly assigned items to your ng-repeat.');
            }

          });

          element.on('$destroy', function () {
            $interval.cancel(start, 0);
          });

          //author - mayo
          element.on('mouseenter', function () {
            isHovered = true;
          });

          //author - mayo
          element.on('mouseleave', function () {
            isHovered = false;
          });

        };
      }

    };
  });

  /**
   * 菜单选中指令
   */
  mod.directive('mtMenushow', function () {
    return {
      restrict: 'A',
      link: function (scope, element) {

        scope.$watch(element, function () {
          var list = element,
              items = element.find('a'),
              itemFirst;

          itemFirst = angular.element(items[0]);

          // 设置当前菜单选中状态
          if (itemFirst.length > 0 && itemFirst[0].href == location.href) {
            itemFirst.parent().addClass("current-page").parent('ul').slideDown().parent().addClass('active');
          }

        });

      }
    };
  });

  mod.directive('mtCompile', function ($compile) { 
      return function (scope, element, attrs) { 
          scope.$watch( 
            function (scope) { 
                  
                return scope.$eval(attrs.mtCompile); 
            }, 
            function (value) { 
                element.html(value); 
                $compile(element.contents())(scope); 
            } 
          ); 
      }; 
  });

  mod.directive('iframeAutoHeight', function($window){

    return {
        restrict: 'A',
        link: link,
        require: '?ngModel'
      };
      function link(scope, element, attrs, ngModel) {
  
        var option = scope.$eval(attrs.iframeAutoHeight);
        // var winowHeight = $window.innerHeight;
        var winowHeight = $window.parent.innerHeight;
        var headerHeight = option.headerHeight;
        var footerHeight = option.footerHeight;
        console.log(element);
        element.css('min-height', (winowHeight - headerHeight - footerHeight -5) + 'px');
            
      };
    
  });

  // 存取后台数据
  // 参数说明:
  // url          - 后台服务地址，字符串      ，必需
  // params       - 参数对象    ，JS对象      ，可选
  // method       - HTTP方法    ，字符串      ，可选 ('GET', 'POST', 'PUT', 'DELETE')
  // config       - 配置对象    ，JS对象      ，可选 (参考$http config)
  mod.provider('reqDataByAjax', mtAjaxProvider);
  mod.provider('mtAjax', mtAjaxProvider);
  function mtAjaxProvider() {
    var contextPath = '';
    /*
		(function () {
            var href = $('<a>').attr('href', '#').prop('href');
            var i = href.indexOf('/html/');
            return i > 0 ? href.substring(0, i) : '';
        })();
		*/
    var unauthorizedHandler = function (response) {
      location.replace(response.headers('Location'));
    };
    var notFoundHandler = function (response) {
    };
    var errorHandler = function (response) {
    };
    this.setUnauthorizedHandler = function (handler) {
      unauthorizedHandler = handler;
    };
    this.setNotFoundHandler = function (handler) {
      notFoundHandler = handler;
    };
    this.setErrorHandler = function (handler) {
      errorHandler = handler;
    };
    this.setContextPath = function (context) {
      contextPath = context;
    };
    this.$get = function ($http, $q, $log) {
      return function (url, params, method, config) {
        var deferred = $q.defer();
        method || (method = 'GET');
        config || (config = {});
        config.url || (config.url = url[0] == '/' ? contextPath + url : url);
        config.method || (config.method = method);
        config.headers || (config.headers = {});
        if (config.method == 'GET' || config.data)
          config.params || (config.params = params);
        else
          config.data = params;
        config.paramSerializer = '$httpParamSerializerJQLike';
        config.headers['X-Requested-With'] = 'XMLHttpRequest';
        $http(config).then(function (response) {
          if (response.data.data && response.data.params) {
            response.data.data.params = response.data.params;
            deferred.resolve(response.data.data);
          } else {
            deferred.resolve(response.data);
          }
        }, function (response) {
          $log.error('mtAjax failed:', response.status, '(' + response.statusText + ')', config);
          switch (response.status) {
          case 401:
            unauthorizedHandler(response);
            break;
          case 404:
            notFoundHandler(response);
            break;
          default:
            errorHandler(response);
          }
          deferred.reject(response);
        });
        return deferred.promise;
      };
    };
  }
  mod.factory('mtShowTab', function () {
    return window['_'] ? _.debounce(mtShowTab, 150) : mtShowTab;
    function mtShowTab(tabContentId) {
      if (tabContentId[0] != '#')
        tabContentId = '#' + tabContentId;
      var el = $('[data-toggle="tab"][href="' + tabContentId + '"],[data-toggle="tab"][data-target="' + tabContentId + '"]');
      if (el.length) {
        el.parent('li').removeClass('active');
        el.first().tab('show');
      }
    }
  });
  /**mtShowModal 的 option设置方法 option = {show: true,backdrop: 'static'}
    option ="hide"
  **/
  mod.factory('mtShowModal', function () {
    return window['_'] ? _.debounce(mtShowModal, 150) : mtShowModal;
    function mtShowModal(modalId, option) {
      if (modalId[0] != '#')
        modalId = '#' + modalId;
      // $(modalId).modal('show');
      if(option){
        $(modalId).modal(option);
      }else if(option == "hide"){
        $(modalId).modal('hide');
      }else{
        $(modalId).modal('show');
      }
    }
  });
  mod.factory('mtOpenTreeFolder', function () {
    return window['_'] ? _.debounce(mtOpenTreeFolder, 150) : mtOpenTreeFolder;
    function mtOpenTreeFolder(treeId) {
      if (treeId[0] != '#')
        treeId = '#' + treeId;
      var el = $(treeId);
      var selectedItem = el.find('.tree-branch.tree-selected');
      el.tree('openFolder', selectedItem);
    }
  });
  mod.factory('mtUpdateTreeItem', function () {
    return window['_'] ? _.debounce(mtUpdateTreeItem, 150) : mtUpdateTreeItem;
    function mtUpdateTreeItem(treeId, data) {
      if (treeId[0] != '#')
        treeId = '#' + treeId;
      var el = $(treeId);
      var selectedItem = el.find('.tree-branch.tree-selected');
      selectedItem.data(data);
      selectedItem.children('.tree-branch-header,.tree-item-name').find('.tree-label').text(data.name);
    }
  });
  mod.factory('mtRefreshTree', function () {
    return window['_'] ? _.debounce(mtRefreshTree, 150) : mtRefreshTree;
    function mtRefreshTree(treeId) {
      if (treeId[0] != '#')
        treeId = '#' + treeId;
      var el = $(treeId);
      el.find('.tree-branch, .tree-item').not('.hide').remove();
      el.tree('render');
    }
  });
  mod.factory('mtRefreshTreeFolder', function () {
    return window['_'] ? _.debounce(mtRefreshTreeFolder, 150) : mtRefreshTreeFolder;
    function mtRefreshTreeFolder(treeId) {
      if (treeId[0] != '#')
        treeId = '#' + treeId;
      var el = $(treeId);
      var selectedItem = el.find('.tree-branch.tree-selected');
      el.tree('refreshFolder', selectedItem);
    }
  });
  mod.factory('mtRefreshTreeParentFolder', function () {
    return window['_'] ? _.debounce(mtRefreshTreeParentFolder, 150) : mtRefreshTreeParentFolder;
    function mtRefreshTreeParentFolder(treeId) {
      if (treeId[0] != '#')
        treeId = '#' + treeId;
      var el = $(treeId);
      var selectedItem = el.find('.tree-branch.tree-selected').parent().closest('.tree-branch');
      el.tree('refreshFolder', selectedItem);
    }
  });
  mod.factory('mtResizeTable', function () {
    return window['_'] ? _.debounce(mtResizeTable, 150) : mtResizeTable;
    function mtResizeTable(tableId) {
      if (tableId[0] != '#')
        tableId = '#' + tableId;
      var api = $(tableId).DataTable();
      var option = api.init();
      api.columns.adjust();
      option && option.scroller && api.scroller.measure();
    }
  });
  mod.factory('mtRefreshTable', function () {
    return window['_'] ? _.debounce(mtRefreshTable, 150) : mtRefreshTable;
    function mtRefreshTable(tableId, reset) {
      if (tableId[0] != '#')
        tableId = '#' + tableId;
      var api = $(tableId).DataTable();
      api.draw(!!reset);
    }
  });
  mod.factory('mtReInitTable', function ($compile) {
    return window['_'] ? _.debounce(mtReInitTable, 150) : mtReInitTable;
    function mtReInitTable(tableId, option, tableDivId, templateUrl, tmpScope) {
      if (tableId[0] != '#')
        tableId = '#' + tableId;
      var api = $(tableId).DataTable();
      api.destroy(true);
      $(tableId).empty();
      
      
      var htmlcontent = $(tableDivId);
      htmlcontent.load(templateUrl);
      $compile(htmlcontent.contents())(tmpScope);

      
      $(tableId).DataTable(option);
    }
  });
  mod.factory('mtGetTableSelection', function () {
    return function mtGetTableSelection(tableId) {
      if (tableId[0] != '#')
        tableId = '#' + tableId;
      var api = $(tableId).DataTable();
      return Array.prototype.slice.call(api.rows('.selected').data(), 0);
    };
  });
  mod.factory('mtGetTableCheck', function () {
    return function mtGetTableCheck(tableId, key) {
      if (tableId[0] != '#')
        tableId = '#' + tableId;
      var api = $(tableId).DataTable();

      var batchData = [];
      var batchTr = $(tableId).find(":checkbox:checked");
      if(batchTr.length == 0){
        return batchData;
      }
      for(var i = 0; i < batchTr.length; ++i){
          // var indexNumb = batchTr.eq(i).parent().parent().find(".approval").attr('href').slice(1);
          // batchData[i]=$("#publish_table").DataTable().row(indexNumb).data();

          batchData.push({});
          batchData[i][key]=batchTr.eq(i).attr(key);
         
      }

      return batchData;
      // return Array.prototype.slice.call(api.rows('.selected').data(), 0);
    };
  });
  mod.factory('mtGetContextPath', function () {
    var path = function () {
        var href = $('<a>').attr('href', '#').prop('href');
        var i = href.indexOf('/html/');
        return i > 0 ? href.substring(0, i) : '';
      }();
    return function () {
      return path;
    };
  });
  mod.factory('mtRefreshEcharts', function () {
    return window['_'] ? _.debounce(mtRefreshEcharts, 150) : mtRefreshEcharts;
    function mtRefreshEcharts(echartsId, option) {
      if (echartsId[0] != '#')
        echartsId = '#' + echartsId;
      var el = $(echartsId);
      var myChart = echarts.init(el[0]);
      
      if (angular.isObject(option)) { 
          myChart.setOption(option); 
      } 

    }
  });
  function makeEventHandler(scope, element, attrs, eventType) {
    var attrName;
    // build attrName
    $.each(eventType.split('.').reverse(), function (i, val) {
      val = val.toLowerCase();
      if (!attrName)
        attrName = val;
      else
        attrName += val.substr(0, 1).toUpperCase() + val.substr(1);
    });
    return function () {
      var args = [
          eventType,
          element
        ], $event = [];
      args.push.apply(args, arguments);
      $event.push.apply($event, arguments);
      if (scope.$$phase) {
        if (attrs[attrName])
          scope.$eval(attrs[attrName], {
            params: args,
            $event: $event
          });
        scope.$root.$broadcast.apply(scope.$root, args);
      } else {
        scope.$apply(function () {
          if (attrs[attrName])
            scope.$eval(attrs[attrName], {
              params: args,
              $event: $event
            });
          scope.$root.$broadcast.apply(scope.$root, args);
        });
      }
    };
  }
  function processEchartsLineBarOption(option, seriesIndex, data) {
    var series = option.series[seriesIndex];
    option.legend && (option.legend.data = data.rows);
    var axisIndex = typeof series.xAxisIndex === 'undefined' ? 0 : series.xAxisIndex;
    var axis = option.xAxis instanceof Array ? option.xAxis[axisIndex] : option.xAxis;
    var axisType = axis.type || 'category';
    axisType === 'category' && (axis.data = data.cols);
    var axisIndex = typeof series.yAxisIndex === 'undefined' ? 0 : series.yAxisIndex;
    var axis = option.yAxis instanceof Array ? option.yAxis[axisIndex] : option.yAxis;
    var axisType = axis.type || 'value';
    axisType === 'category' && (axis.data = data.cols);
    series.name = data.rows[seriesIndex];
    series.data = data.data[seriesIndex];
    return option;
  }
  function processEchartsPieMapGaugeOption(option, seriesIndex, data) {
    var series = option.series[seriesIndex];
    option.legend && (option.legend.data = data.cols);
    var seriesData = [];
    for (var i = 0; i < data.data[seriesIndex].length && i < data.cols.length; ++i) {
      seriesData[i] = {
        value: data.data[seriesIndex][i],
        name: data.cols[i]
      };
    }
    series.name = data.rows[seriesIndex];
    series.data = seriesData;
    return option;
  }
  function processEchartsRadarOption(option, seriesIndex, data) {
    if (seriesIndex !== 0)
      return;
    var series = option.series[seriesIndex];
    option.legend && (option.legend.data = data.rows);
    var seriesData = [];
    for (var i = 0; i < data.data.length && i < data.rows.length; ++i) {
      seriesData[i] = {
        value: data.data[i],
        name: data.rows[i]
      };
    }
    series.data = seriesData;
    return option;
  }
  mod.factory('parseDataForChart', function () {
    return mtParseChartData;
  });
  mod.factory('mtParseChartData', function () {
    return mtParseChartData;
  });
  // 分析数据集
  // 参数说明:
  // rs           - 分析结果集  ，二维对象数组，必需
  // datFieldName - 数值字段名称，字符串      ，必需
  // colFieldName - 列字段名称  ，字符串      ，必需
  // rowFieldName - 行字段名称  ，字符串      ，可选
  // colsFixVal   - 固定列字段值，字符串数组  ，可选
  // rowsFixVal   - 固定行字段值，字符串数组  ，可选
  // nulVal       - 空值显示值  ，数值或字符串，默认 0
  // naVal        - 不存在显示值，数值或字符串，默认 '-'
  function mtParseChartData(rs, datFieldName, colFieldName, rowFieldName, colsFixVal, rowsFixVal, nulVal, naVal) {
    if (datFieldName instanceof Array) {
      var cols, rows = [], data = [];
      for (var i in datFieldName) {
        var fn = typeof datFieldName[i] === 'string' ? datFieldName[i] : datFieldName[i].fieldName;
        var dn = typeof datFieldName[i] === 'string' ? datFieldName[i] : datFieldName[i].displayName;
        var ret = mtParseChartData(rs, fn, colFieldName, rowFieldName, colsFixVal, rowsFixVal, nulVal, naVal);
        cols = ret.cols;
        for (var j in ret.rows)
          rows.push(ret.rows[j] + dn);
        Array.prototype.push.apply(data, ret.data);
      }
      return {
        cols: cols,
        rows: rows,
        data: data
      };
    }
    var colsFixed = colsFixVal && colsFixVal instanceof Array;
    var rowsFixed = rowsFixVal && rowsFixVal instanceof Array;
    var cols = colsFixed ? colsFixVal : [];
    var rows = rowsFixed ? rowsFixVal : [];
    var data = [];
    var ri = -1, rv = null, d = null;
    // 单系列数据
    if (!rowFieldName) {
      if (!rowsFixed) {
        rows[++ri] = '\u6570\u503c';
      } else {
        ri = rows.length ? 0 : -1;
      }
      d = [];
      ri > -1 && (data[ri] = d);
    }
    for (var i = 0; i < rs.length; ++i) {
      var item = rs[i];
      // 一个系列开始了?
      if (rowFieldName && item[rowFieldName] != rv) {
        rv = item[rowFieldName];
        ri = rows.indexOf(rv);
        if (ri == -1 && !rowsFixed)
          ri = rows.push(rv) - 1;
        d = ri > -1 && data[ri] || [];
        ri > -1 && (data[ri] = d);
      }
      // 查找列位置
      var ci, cv;
      if (!colFieldName) {
        if (!rowFieldName) {
          ci = i;
          !colsFixed && (cols[ci] = i + 1);
        } else {
          ci = 0;
          !cols.length && (cols[ci] = 1);
        }
      } else {
        cv = item[colFieldName];
        ci = cols.indexOf(cv);
        if (ci == -1 && !colsFixed)
          ci = cols.push(cv) - 1;
      }
      // 填入数据
      ci > -1 && datFieldName && (d[ci] = item[datFieldName]);
    }
    // 标记不存在数据
    nulVal === undefined && (nulVal = 0);
    naVal === undefined && (naVal = '-');
    for (var i = 0; i < rows.length; ++i) {
      var r = data[i] || (data[i] = []);
      for (var j = 0; j < cols.length; ++j) {
        if (r[j] === null)
          r[j] = nulVal;
        else if (r[j] === undefined)
          r[j] = naVal;
      }
    }
    // 返回处理结果
    return {
      rows: rows,
      cols: cols,
      data: data
    };
  }
  function makeDependsLoader(js, css) {
    var loadingStatus;
    return function ($q) {
      var deferred = $q.defer();
      if (loadingStatus === true || window.LazyLoad === undefined) {
        deferred.resolve(true);
        return deferred.promise;
      } else if (loadingStatus instanceof Array) {
        loadingStatus.push(deferred);
        return deferred.promise;
      }
      loadingStatus = [deferred];
      css && LazyLoad.css(css);
      LazyLoad.js(js, function () {
        for (var i in loadingStatus)
          loadingStatus[i].resolve(true);
        loadingStatus = true;
      });
      return deferred.promise;
    };
  }
}());